package com.zsw.dubbo.console;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;

import javax.xml.bind.PropertyException;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;

import com.zsw.dubbo.util.PropertyUtil;
import com.zsw.dubbo.util.StringUtil;

/**
 * 系统控制台类
 * 
 * @author daze
 * 
 */
public class SysConsole implements Runnable {
	private Logger log = Logger.getLogger(this.getClass());

	public static String FGF_ML = " ";
	public static String FGF_ARG = " ";

	public static List<Class<?>> mainConsoles;

	private static SysConsole consoleInit;

	private List<String> proSList;
	private List<Properties> proList;
	private Properties pps;
	private Map<String, ConsoleB> methods;
	private Scanner scanner;
	private Thread thread;
	private int x;
	public static ApplicationContext app;

	private boolean exit = false;

	public SysConsole() {
		consoleInit = init();
	}

	public SysConsole(String property) {
		consoleInit = init(property);

	}

	private SysConsole(Properties pps, InputStream in) {
		if (in == null) {
			in = System.in;
		}
		this.scanner = new Scanner(in);
		this.pps = pps;
		mainConsoles = new ArrayList<Class<?>>();
		mainConsoles.add(MainConsole.class);
		methods = new HashMap<String, ConsoleB>();
		initMainConsoles();
		initProperties();
	}

	public SysConsole(ApplicationContext app) {
		SysConsole.app = app;
		consoleInit = init();
	}

	public void initProperties() {
		if (pps == null) {
			pps = new Properties();
		}
		if (proSList == null) {
			proSList = new ArrayList<String>();
		}
		if (proList == null) {
			proList = new ArrayList<Properties>();
		}
		for (String str : proSList) {
			Properties ps = PropertyUtil.getProperties(str);
			proList.add(ps);
		}
		for (Properties ps : proList) {
			for (Object o : ps.keySet()) {
				pps.put(o, ps.get(o));
			}
		}
	}

	public void initMainConsoles() {
		for (Class<?> clazz : mainConsoles) {
			for (Method method : clazz.getDeclaredMethods()) {
				try {
					ConsoleB cb = new ConsoleB(clazz, method.getName());
					methods.put(method.getName(), cb);
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (NoSuchFieldException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static SysConsole getSysConsole() {
		return SysConsole.consoleInit;
	}

	public synchronized static SysConsole init() {
		if (SysConsole.consoleInit == null) {
			SysConsole.consoleInit = new SysConsole(null, null);
			consoleInit.start();
		}
		return SysConsole.consoleInit;
	}

	public synchronized static SysConsole init(String properDir) {
		if (SysConsole.consoleInit == null) {
			SysConsole.consoleInit = new SysConsole(
					PropertyUtil.getProperties(properDir), null);
			consoleInit.start();
		}
		return SysConsole.consoleInit;
	}

	public synchronized static SysConsole init(Properties pps) {
		if (SysConsole.consoleInit == null) {
			SysConsole.consoleInit = new SysConsole(pps, null);
			consoleInit.start();
		}
		return SysConsole.consoleInit;
	}

	public void start() {
		if (thread == null) {
			thread = new Thread(this, "SysConsole");
		}
		if (!thread.isAlive()) {
			thread.start();
			log.info("控制台已经启动");
		}
	}

	@Override
	public void run() {
		while (!exit && scanner.hasNextLine()) {
			String str = scanner.nextLine();
			if (!StringUtil.stringProving(str)) {
				continue;
			}
			Console c = new Console(str);
			ConsoleB cb = null;
			try {
				cb = c.analyze();
				if (cb != null && cb.getClazz() == null) {
					StringBuffer sb = new StringBuffer();
					sb.append("命令:").append(c.getConsole()).append("|");
					sb.append("执行目标:").append(cb.getClassName()).append(":");
					sb.append(cb.getMethodName()).append("|");
					sb.append("参数:").append(c.getSargs()).append("\n");
					sb.append("目标类:").append(cb.getClassName()).append("未找到!");
					System.err.println(sb.toString());
					continue;
				}
				try {
					outReturn(cb.getClassName() + ":" + cb.getMethodName());
					Object ret = cb.send(c.getArgs());
					outReturn(ret);
					x = 0;
				} catch (NullPointerException e) {
					System.err.println(e.getMessage());
				}
			} catch (PropertyException e) {
				System.err.println(e.getMessage());
			} catch (NullPointerException e) {
				ConsoleB mainCb = methods.get(c.getConsole());
				if (mainCb != null) {
					try {
						outReturn(mainCb.getClassName() + ":"
								+ mainCb.getMethodName());
						Object ret = mainCb.send(c.getArgs());
						outReturn(ret);
						x = 0;
					} catch (IllegalArgumentException e1) {
						// e1.printStackTrace();
						System.err.println(paraErr(c, mainCb));
					} catch (IllegalAccessException e1) {
						e1.printStackTrace();
					} catch (InvocationTargetException e1) {
						e1.printStackTrace();
					} catch (NullPointerException e1) {
						e1.printStackTrace();
					}catch(Exception e1){
						e.printStackTrace();
					}
				} else {
					x++;
					StringBuffer sb = new StringBuffer("未找到命令!");
					if (x >= 3) {
						sb.append("如果您不知道可以输入什么命令,可使用'help'命令来获取帮助");
					}
					System.err.println(sb);
				}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				System.err.println(paraErr(c, cb));
			} catch (IllegalArgumentException e) {
				System.err.println(paraErr(c, cb));
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}catch (NoSuchFieldException e) {
				e.printStackTrace();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		// if (StringUtil.stringProving(instruction)) {
		// System.err.println("未找到该命令:" + instruction);
		// }
	}

	private void outReturn(Object... ret) {
		StringBuffer sb = new StringBuffer();
		if (StringUtil.stringProving(ret)) {
			for (Object obj : ret) {
				sb.append(">");
				sb.append(obj);
			}
		}
		System.out.println(sb.toString());
	}

	private String paraErr(Console c, ConsoleB cb) {
		StringBuffer sb = new StringBuffer();
		sb.append("命令:").append(c.getConsole()).append("|");
		sb.append("执行目标:").append(cb.getClassName()).append(":");
		sb.append(cb.getMethodName()).append("|");
		sb.append("参数:").append(c.getSargs()).append("\n");
		sb.append("说明:").append(cb.getMessage());
		StringBuffer s = new StringBuffer("参数错误!");
		try {
			for (Method m : cb.getClazz().getMethods()) {
				if (m.getName().equals(cb.getMethodName())) {
					for (Class<?> cla : m.getParameterTypes()) {
						s.append(cla.getSimpleName()).append(",");
					}
					break;
				}
			}
		} catch (Exception e) {
		}
		return sb.toString() + s.toString();
	}

	public List<String> getProSList() {
		return proSList;
	}

	public void setProSList(List<String> proSList) {
		this.proSList = proSList;
	}

	public List<Properties> getProList() {
		return proList;
	}

	public void setProList(List<Properties> proList) {
		this.proList = proList;
	}

	public Scanner getScanner() {
		return scanner;
	}

	public void setScanner(Scanner scanner) {
		this.scanner = scanner;
	}

	public Map<String, ConsoleB> getMethods() {
		return methods;
	}

	public Properties getPps() {
		return pps;
	}

	public void setPps(Properties pps) {
		this.pps = pps;
	}

	public String demo(String s) {
		return "demo" + s;
	}

}
